package org.tamal.tools;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.UnsupportedCharsetException;

import com.itextpdf.text.Anchor;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chapter;
import com.itextpdf.text.ChapterAutoNumber;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.GreekList;
import com.itextpdf.text.Image;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.RomanList;
import com.itextpdf.text.Section;
import com.itextpdf.text.ZapfDingbatsList;
import com.itextpdf.text.ZapfDingbatsNumberList;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.LineSeparator;

/**
 * This class generates PDF document.
 * @author Tamal Kanti Nath
 */
public final class ItextPdfDemo {
    private static final int DEFAULT_SIZE = 12;
    private static final String URL = "http://code.google.com/p/tamal-project/";
    private static final Font LINK = new Font(FontFamily.HELVETICA,
            DEFAULT_SIZE, Font.UNDERLINE | Font.BOLD, BaseColor.BLUE);
    private static final Font H1 = new Font(FontFamily.HELVETICA, 16,
            Font.BOLD, BaseColor.ORANGE);
    private static final Font H2 = new Font(FontFamily.HELVETICA, 14,
            Font.BOLDITALIC, BaseColor.ORANGE);
    private static final Font H3 = new Font(FontFamily.HELVETICA, DEFAULT_SIZE,
            Font.BOLD, BaseColor.ORANGE);
    private Document document = new Document();
    private PdfWriter writer;

    /**
     * Constructor.
     * @param file file
     * @throws DocumentException exception
     * @throws IOException exception
     */
    public ItextPdfDemo(String file) throws IOException, DocumentException {
        writer = PdfWriter.getInstance(document, new FileOutputStream(file));
        document.open();
        document.addAuthor("Tamal Kanti Nath");
        document.addCreator("tamal");
        document.addHeader("Application", "Web Application (1.4)");
        document.addKeywords("PDF");
        document.addSubject("Web Application PDF report");
        document.addTitle("PDF Report");
    }

    private void showElements() throws DocumentException, IOException {
        Chapter chapter = new ChapterAutoNumber(new Paragraph("Elements", H1));
        Section section = chapter.addSection(new Paragraph("List", H2));
        Section sub = section.addSection(new Paragraph("List Level", H3));
        sub.add(getListTree());
        sub = section.addSection(new Paragraph("List Types", H3));
        addListTypes(sub);
        section = chapter.addSection(new Paragraph("Anchors", H2));
        section.add(getAnchors());
        section = chapter.addSection(new Paragraph("Graphics", H2));
        sub = section.addSection(new Paragraph("Line Seperators", H3));
        sub.add(new Chunk(new LineSeparator(2, 90, BaseColor.GREEN,
                Element.ALIGN_CENTER, 0)));
        sub = section.addSection(new Paragraph("Image", H3));
        Image image = Image.getInstance("../jsf/src/main/webapp/content/bullet.png");
        sub.add(new Chunk(image, 100, 0, true));
        document.add(chapter);
    }

    private static Paragraph getAnchors() {
        Paragraph paragraph = new Paragraph();
        Anchor anchor = new Anchor("Anchor (internal)", LINK);
        anchor.setReference("#anchor");
        paragraph.add(anchor);
        paragraph.add(Chunk.NEWLINE);
        anchor = new Anchor("Anchor (external)", LINK);
        anchor.setReference(URL);
        paragraph.add(anchor);
        paragraph.add(Chunk.NEWLINE);
        Chunk chunk = new Chunk("Chunk (local goto)", LINK);
        chunk.setLocalGoto("#chunk");
        paragraph.add(chunk);
        paragraph.add(Chunk.NEWLINE);
        chunk = new Chunk("Chunk (remote goto)", LINK);
        chunk.setRemoteGoto("iText.pdf", 2);
        paragraph.add(chunk);
        paragraph.add(Chunk.NEWLINE);
        chunk = new Chunk("Chunk (anchor)", LINK);
        chunk.setAnchor(URL);
        paragraph.add(chunk);
        paragraph.add(Chunk.NEWLINE);
        anchor = new Anchor("Anchor (name)");
        anchor.setName("anchor");
        paragraph.add(anchor);
        paragraph.add(Chunk.NEWLINE);
        chunk = new Chunk("Chunk (Local Destination)");
        chunk.setLocalDestination("chunk");
        paragraph.add(chunk);
        paragraph.add(Chunk.NEWLINE);
        return paragraph;
    }

    private static void addListTypes(Section sub) {
        List list = new List();
        list.add("Unordered List");
        sub.add(list);
        list = new List(List.ORDERED);
        list.add("Numerical List");
        sub.add(list);
        list = new List(List.ORDERED, List.ALPHABETICAL);
        list.add("Alphabetical (uppercase) List");
        sub.add(list);
        list = new List(List.ORDERED, List.ALPHABETICAL);
        list.setLowercase(List.LOWERCASE);
        list.add("Alphabetical (lowercase) List");
        sub.add(list);
        list = new RomanList();
        list.add("Roman (uppercase) List");
        sub.add(list);
        list = new RomanList(List.LOWERCASE, DEFAULT_SIZE);
        list.add("Roman (lowercase) List");
        sub.add(list);
        list = new GreekList();
        list.add("Greek (uppercase) List");
        sub.add(list);
        list = new GreekList(List.LOWERCASE, DEFAULT_SIZE);
        list.add("Greek (lowercase) List");
        sub.add(list);
        list = new ZapfDingbatsNumberList(0);
        list.add("ZapfDingbatsNumberList 0 - 3");
        sub.add(list);
        list = new ZapfDingbatsList(43);
        list.add("ZapfDingbatsList range: 33 - 126, 161-254");
        sub.add(list);
    }

    private static List getListTree() {
        List l1 = new List();
        List l2 = new List(List.ORDERED);
        List l3 = new List(List.ORDERED, List.ALPHABETICAL);
        List l4 = new List(List.ORDERED, List.ALPHABETICAL);
        l4.setLowercase(List.LOWERCASE);
        ListItem li1 = new ListItem("Level 1");
        ListItem li2 = new ListItem("Level 2");
        ListItem li3 = new ListItem("Level 3");
        ListItem li4 = new ListItem("Level 4");
        l4.add(li4);
        li3.add(l4);
        l3.add(li3);
        li2.add(l3);
        l2.add(li2);
        li1.add(l2);
        l1.add(li1);
        return l1;
    }

    private void showDirectContent() throws DocumentException, IOException {
        Chapter chapter = new ChapterAutoNumber(new Paragraph("Direct Content",
                H1));
        chapter.addSection("Show Text Aligned");
        chapter.addSection("Rectangle");
        document.add(chapter);
        PdfContentByte over = writer.getDirectContent();
        over.saveState();
        over.setLineWidth(5);
        //over.concatCTM(1, 0, 0.1f, 1, 0, 0);
        over.rectangle(document.right() - 100, document.top() - 100, 100, 100);
        over.setColorStroke(BaseColor.RED);
        over.setColorFill(BaseColor.ORANGE);
        over.fillStroke();
        over.concatCTM(1, 0, 0.1f, 1, 0, 0);
        over.rectangle(document.right() - 220, document.top() - 150, 100, 100);
        over.setColorFill(BaseColor.BLUE);
        over.fillStroke();
        over.restoreState();
        over.setFontAndSize(BaseFont.createFont(), DEFAULT_SIZE);
        over.showTextAligned(Element.ALIGN_RIGHT, "Hello World",
                document.right() - 50, document.top() - 50, 45);
        PdfContentByte under = writer.getDirectContentUnder();
        under.saveState();
        under.rectangle(document.left(), document.bottom(), document.right()
                - document.left(), document.top() - document.bottom());
        under.setLineWidth(3);
        under.setColorStroke(BaseColor.GRAY);
        under.setColorFill(BaseColor.WHITE);
        under.fillStroke();
        under.restoreState();
    }

    private void showInformation() throws DocumentException {
        Chapter chapter = new ChapterAutoNumber(
                new Paragraph("Information", H1));
        Section section = chapter.addSection(new Paragraph("Document", H2));
        section.add(getDocumentInformation());
        section = chapter.addSection(new Paragraph("Writer", H2));
        section.add(getWriterInformation());
        document.add(chapter);
    }

    private List getDocumentInformation() {
        List list = new List(List.UNORDERED);
        list.setListSymbol("* ");
        list.add("Page Number = " + document.getPageNumber());
        list.add("Page Size = " + document.getPageSize());
        list.add("Left = " + document.left());
        list.add("Right = " + document.right());
        list.add("Top = " + document.top());
        list.add("Bottom = " + document.bottom());
        list.add("Left Margin = " + document.leftMargin());
        list.add("Right Margin = " + document.rightMargin());
        list.add("Top Margin = " + document.topMargin());
        list.add("Bottom Margin = " + document.bottomMargin());
        //list.add("Product = " + Document.getProduct());
        //list.add("Release = " + Document.getRelease());
        //list.add("Version = " + Document.getVersion());
        list.add("Style = " + document.getHtmlStyleClass());
        list.add("On Load = " + document.getJavaScript_onLoad());
        list.add("On Unload = " + document.getJavaScript_onUnLoad());
        return list;
    }

    private List getWriterInformation() {
        List list = new List();
        list.add("Compression Level = " + writer.getCompressionLevel());
        list.add("Current Document Size = " + writer.getCurrentDocumentSize());
        list.add("Current Page Number = " + writer.getCurrentPageNumber());
        list.add("Writer Page Number = " + writer.getPageNumber());
        list.add("PDFX Conformance = " + writer.getPDFXConformance());
        list.add("Run Direction = " + writer.getRunDirection());
        list.add("Space Character Ratio = " + writer.getSpaceCharRatio());
        list.add("Vertical Position = " + writer.getVerticalPosition(false));
        list.add("Vertical Position (new line) = "
                + writer.getVerticalPosition(true));
        // list.add("Acro Form = " + writer.getAcroForm());
        list.add("Box Size (crop) = " + writer.getBoxSize("crop"));
        list.add("Box Size (trim) = " + writer.getBoxSize("trim"));
        list.add("Box Size (art) = " + writer.getBoxSize("art"));
        list.add("Box Size (bleed) = " + writer.getBoxSize("bleed"));
        // list.add("Color Space = " + writer.getDefaultColorspace());
        list.add("Direct Content = " + writer.getDirectContent());
        list.add("Direct Content Under = " + writer.getDirectContentUnder());
        // list.add("Extra Catalog = " + writer.getExtraCatalog());
        list.add("Group = " + writer.getGroup());
        // list.add("Info = " + writer.getInfo());
        // list.add("OC Properties = " + writer.getOCProperties());
        list.add("Page Event = " + writer.getPageEvent());
        list.add("Page Reference = " + writer.getPageReference(1));
        list.add("Writer Page Size = " + writer.getPageSize());
        list.add("PDF Indirect Reference = "
                + writer.getPdfIndirectReference());
        list.add("Root Outline = " + writer.getRootOutline());
        list.add("Structure Tree Root = " + writer.getStructureTreeRoot());
        list.add("Tabs = " + writer.getTabs());
        list.add("Close Stream = " + writer.isCloseStream());
        list.add("Full Compression = " + writer.isFullCompression());
        list.add("Page Empty = " + writer.isPageEmpty());
        list.add("Paused = " + writer.isPaused());
        list.add("PDFX = " + writer.isPdfX());
        list.add("RGB Transparency Blending = "
                + writer.isRgbTransparencyBlending());
        list.add("Strict Image Sequence = " + writer.isStrictImageSequence());
        list.add("Tagged = " + writer.isTagged());
        list.add("User Properties = " + writer.isUserProperties());
        return list;
    }

    private void showFonts() throws DocumentException {
        Chapter chapter = new ChapterAutoNumber(new Paragraph("Fonts", H1));
        Section section = chapter.addSection(new Paragraph("Registration", H2));
        int count = FontFactory.registerDirectories();
        section.add(new Paragraph("Fonts Registered = " + count));
        section = chapter.addSection(new Paragraph("Bengali Fonts", H2));
        PdfPTable table = new PdfPTable(new float[] {1, 2});
        table.setSpacingBefore(DEFAULT_SIZE);
        table.setSpacingAfter(DEFAULT_SIZE);
        String str = "তমাল কান্তি নাথ (Tamal Kanti Nath)";
        Font font;
        for (String f : FontFactory.getRegisteredFamilies()) {
            if (new java.awt.Font(f, 0, DEFAULT_SIZE).canDisplay('\u0995')) {
                try {
                    font = FontFactory.getFont(f, BaseFont.IDENTITY_H);
                } catch (UnsupportedCharsetException e) {
                    font = FontFactory.getFont(f);
                }
                table.addCell(f);
                table.addCell(new Phrase(str, font));
            }
        }
        section.add(table);
        document.add(chapter);
    }

    /**
     * Closes the document.
     */
    public void close() {
        document.close();
    }

    /**
     * Starting point.
     * @param args parameters
     * @throws Exception exception
     */
    public static void main(String[] args) throws Exception {
        String file = "/tmp/iText.pdf";
        ItextPdfDemo pdf = new ItextPdfDemo(file);
        pdf.showInformation();
        pdf.showElements();
        pdf.showDirectContent();
        pdf.showFonts();
        pdf.close();
        if ("Linux".equalsIgnoreCase(System.getProperty("os.name"))) {
            Runtime.getRuntime().exec(new String[] {"gnome-open", file});
        } else {
            Runtime.getRuntime().exec(
                    new String[] {"explorer", file.replace('/', '\\')});
        }
    }

}
